// AntdSelect.jsx

import React, { useEffect, useState } from 'react'
import { useDebounce } from 'react-use'
import { Select, message } from 'antd'
import './index.less'
import qs from 'qs'
const { Option } = Select

/**
 * Select组件
 * @param value                   Antd Select value
 * @param onChange                Antd Select onChange
 * @param handleList              外部处理并返回list数据
 * @param url                     String 请求接口
 * @param ajaxData                Object 接口入参
 * @param debounceMs              Number 防抖延时时间
 * @param remote                  Boolean 是否为远程搜索 默认true
 * @param mode                    Antd Select mode, 设置 Select 的模式为多选或标签  multiple | tags
 * @param echoOptions             回显的list数据
 * @param propsPageSize           每页搜索数量 默认15
 * @param curPageKey              String 分页请求页码键值 'curPage'
 * @param queryKey                String 搜索键值 默认 'queryKeyword'
 * @param disabledKey             String 指定要使用的 disabled 字段 默认 'disabled'
 * @param labelKey                String 指定要显示的 label 字段 默认 'label'
 * @param valueKey                String 指定要显示的 value 字段 默认 'value'
 * @param rich                    Boolean Option是否显示更多信息 默认 false
 * @param rightLabelKey           String 指定要显示的 地区 字段 默认 ''
 * @param bottomLabelKey          String 指定要显示的 公司/组 字段 默认 ''
 * @param rest                    Antd Select API
 * @returns {JSX.Element}
 */
export default ({
                  axios,
                  value,
                  onChange,
                  handleList,
                  url,
                  ajaxData,
                  debounceMs,
                  remote = true,
                  mode,
                  echoOptions,
                  propsPageSize,
                  curPageKey,
                  queryKey,
                  labelKey,
                  disabledKey,
                  valueKey,
                  rich,
                  rightLabelKey,
                  bottomLabelKey,
                  ...rest
                }) => {
  const [loading, setLoading] = useState(false) // loading
  const [list, setList] = useState([]) // 下列选项
  const [searchText, setSearchText] = useState('') // 搜索文本，防抖用
  const [pageSize, setPageSize] = useState(propsPageSize || 15) // 每页搜索数量
  const [curPage, setCurPage] = useState(0) // 搜索页码
  const [pageSt, setPageSt] = useState(0) // 滚动的距离
  const [lastPage, setLastPage] = useState(false) // 是否是最后一页
  const [_curPageKey, setCurPageKey] = useState(curPageKey ? curPageKey : 'curPage') // 每页搜索数量
  const [_queryKeyword, setQueryKeyword] = useState(queryKey ? queryKey : 'queryKeyword') // 搜索键值
  const [_disabledKey, setDisabledKey] = useState(disabledKey ? disabledKey : 'disabled') // 指定要使用的 disabled 字段
  const [_labelKey, setLabelKey] = useState(labelKey ? labelKey : 'label') // 指定要显示的 label 字段
  const [_valueKey, setValueKey] = useState(valueKey ? valueKey : 'value') // 指定要显示的 value 字段
  const [_rightLabelKey, setCity] = useState(rightLabelKey ? rightLabelKey : '') // 指定要显示的 右侧 字段
  const [_bottomLabelKey, setCompanyName] = useState(bottomLabelKey ? bottomLabelKey : '') // 指定要显示的 底部 字段

  useEffect(() => {
    if (echoOptions?.length) {
      setList(echoOptions)
    }
  }, [])

  useEffect(() => {
    getList()
  }, [curPage])

  // 防抖
  useDebounce(
    () => {
      getList(searchText)
    },
    debounceMs || 300,
    [searchText]
  )

  // 获取列表
  const getList = (val) => {
    setLoading(true)
    const params = {
      pageSize,
      [_curPageKey]: curPage,
      [_queryKeyword]: val || '',
      ...ajaxData
    }
    axios.post(url, qs.stringify(params))
      .then(({ flag, data, msg }) => {
        setLoading(false)
        if (flag) {
          setLastPage(() => {
            if (data.totalRows) {
              // 如果有分页
              return Math.ceil(data.totalRows / pageSize) <= curPage + 1
            } else {
              // 没有分页则不再滚动加载
              return true
            }
          })
          if (curPage === 0) {
            if (Array.isArray(data)) {
              handleList ? handleList2(data) : setList(data)
            } else {
              handleList ? handleList2(data.dataList) : setList(data.dataList)
            }
          } else {
            if (Array.isArray(data)) {
              handleList ? handleList2([...list, ...data]) : setList((value) => [...value, ...data])
            } else {
              handleList ? handleList2([...list, ...data.dataList]) : setList((value) => [...value, ...data.dataList])
            }
          }
        } else {
          message.error(msg || '请求失败')
        }
      })
      .catch((error) => {
        setLoading(false)
        message.error(error.toString().includes('timeout') ? '服务超时' : error.toString())
      })
  }

  // 外部函数处理数据
  const handleList2 = (val) => {
    const list = handleList(val)
    setList(list)
  }

  // 当清空时
  const onClear = (val) => {
    setSearchText(val)
  }

  //  搜索
  const handleSearch = (val) => {
    if (remote) {
      setSearchText(val)
    }
  }

  //  滚动，分页搜索
  const handlePopupScroll = (e) => {
    // scrollTop // 滚动条距元素(不一定是屏幕最顶端)顶部滚动的距离
    // offsetHeight // 元素CSS高度
    // scrollHeight // 文档内容实际高度，包括超出视窗的溢出部分
    e.persist()
    const { target } = e
    const st = target.scrollTop
    if (st === 0 && pageSt) {
      target.scrollTop = pageSt
    }
    if (st + target.offsetHeight + 3 >= target.scrollHeight && !lastPage) {
      setPageSt(st)
      setCurPage(curPage + 1)
    } else {
      setPageSt(0)
    }
  }

  return (
    <Select
      className="custom-select"
      optionLabelProp="label"
      getPopupContainer={(triggerNode) => triggerNode.parentNode}
      filterOption={false}
      allowClear
      mode={mode}
      showSearch
      onSearch={handleSearch}
      onPopupScroll={handlePopupScroll}
      loading={loading}
      value={value}
      dropdownMatchSelectWidth={false}
      onChange={onChange}
      onClear={onClear}
      {...rest}
    >
      {list?.map((item) => {
        return (
          <Option disabled={item[_disabledKey]} value={item[_valueKey]} key={item[_valueKey]} label={item[_labelKey]}>
            {rich ? (
              <>
                <div className="select-top-title">
                  <span className="top-label-key" title={item[_labelKey]}>{item[_labelKey]}</span>
                  {item?.ext[_rightLabelKey] ? (
                    <span className="right-label-key" title={item?.ext[_rightLabelKey]}>{item?.ext[_rightLabelKey]}</span>
                  ) : null}
                </div>
                {item?.ext[_bottomLabelKey] ? <div className="bottom-label-key" title={item?.ext[_bottomLabelKey]}>{item?.ext[_bottomLabelKey]}</div> : null}
              </>
            ) : (
              <p className="label-key" title={item[_labelKey]}>{item[_labelKey]}</p>
            )}
          </Option>
        )
      })}
    </Select>
  )
}

